package com.cloud.common.utils;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.awt.*;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class BaiduMapUtils implements Runnable {

    private static final Logger logger = LoggerFactory.getLogger(BaiduMapUtils.class);

    // 成功数量
    private int success = 0;
    // 失败数量
    private int error = 0;
    // 完成线程数量
    private int finishThread = 0;
    // 耗时(时间戳)
    private long endTime = 0;
    // 地图层级
    private int zoom;
    // x的开始值
    private int xStart;
    // x的结束值
    private int xEnd;
    // y的开始值
    private int yStart;
    // y的结束值
    private int yEnd;
    // 几个线程开始下载地图
    private int threads;
    // 百度地图瓦片地址
    private String mapPath;
    // 瓦片地图存放地址
    private String dir;
    // 是否覆盖之前下载的图片
    private boolean overwrite = false;

    /**
     * 百度地图瓦片下载
     * x1,y1代表的是需要拉取的地图范围的左小角经纬度,x2,y2代表右上角经纬度,
     * z代表需要拉取到的层级,19就是从6-19层都拉取下来
     */
    public BaiduMapUtils(Integer zoom, double x1, double y1, double x2, double y2, Integer threads, String path, String map) {
        this.zoom = zoom;
        List<Integer> tile1 = BaiduMapConvert.getTile(x1, y1, zoom);
        List<Integer> tile2 = BaiduMapConvert.getTile(x2, y2, zoom);
        this.xStart = tile1.get(0);
        this.xEnd = tile2.get(0);
        this.yStart = tile1.get(1);
        this.yEnd = tile2.get(1);
        this.threads = threads;
        if (StringUtils.isEmpty(map)) {
            map = "blue";
        }
        // 蓝底地图
        if ("".equals(map)) {
            this.dir = path + "/blue";
            this.mapPath = "http://api%d.map.bdimg.com/customimage/tile?&x=%d&y=%d&z=%d&udt=20211205&scale=1&ak=5ieMMexWmzB9jivTq6oCRX9j&customid=midnight";
        }
        // 普通地图
        if ("normal".equals(map)) {
            this.dir = path + "/normal";
            this.mapPath = "http://online%d.map.bdimg.com/onlinelabel/?qt=tile&x=%d&y=%d&z=%d&styles=pl&scaler=1&p=1";
        }
        // 带注释地图
        if ("notes".equals(map)) {
            this.dir = path + "/notes";
            this.mapPath = "http://online%d.map.bdimg.com/tile/?qt=tile&x=%d&y=%d&z=%d&styles=sl";
        }
        // 卫星地图
        if ("moons".equals(map)) {
            this.dir = path + "/moons";
            this.mapPath = "http://shangetu%d.map.bdimg.com/it/u=x=%d;y=%d;z=%d;v=009;type=sate&fm=46";
        }
    }

    @Override
    public void run() {
        ExecutorService exec = Executors.newCachedThreadPool();
        Set<Point> set = new HashSet<>();
        int total = (xEnd - xStart + 1) * (yEnd - yStart + 1);
        int split = total / threads;
        int count = 0;
        for (int i = xStart; i <= xEnd; i++) {
            for (int j = yStart; j <= yEnd; j++) {
                set.add(new Point(i, j));
                if (split != 0) {
                    if (++count % split == 0) {
                        ThreadMapUtils threadMap = new ThreadMapUtils(set);
                        threadMap.run(dir, zoom, mapPath, overwrite, success, error, finishThread);
                        exec.execute(threadMap);
                        set = new HashSet<>();
                        endTime = System.currentTimeMillis();
                    }
                }
            }
        }
        if (set.size() > 0) {
            ThreadMapUtils threadMap = new ThreadMapUtils(set);
            threadMap.run(dir, zoom, mapPath, overwrite, success, error, finishThread);
            exec.execute(threadMap);
            endTime = System.currentTimeMillis();
        }
        long t = System.currentTimeMillis();
        while (finishThread < threads) {
            try {
                // 当Split为0时只有一个线程进行任务
                if (split == 0 && finishThread == 1) {
                    break;
                }
                // 当有5个线程但图片小于5张时需要判断如下
                if (total == finishThread) {
                    break;
                }
                Thread.sleep(200);
            } catch (InterruptedException e) {
                logger.error("开启瓦片拉取线程失败:", e.getMessage());
            }
        }
        exec.shutdown();
        logger.info("地图层级:" + zoom + "完成,共耗时:" + (endTime - t) / 1000 + "/秒,成功:" + success
                + "/次,失败:" + error + "/次,完成线程:" + finishThread + ",总线程" + total);
    }


}
